/*
 * Author: Kishore Reddy
 * Url: http://NHelpernet.codeplex.com/
 * Title: NHelper.NET
 * Copyright: � 2009 Kishore Reddy
 * License: LGPL License
 * LicenseUrl: http://NHelpernet.codeplex.com/license
 * Description: A C# based .NET 3.5 Open-Source collection of reusable components.
 * Usage: Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Web;
using System.IO;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Globalization;
using System.Drawing.Imaging;
using System.Collections.Specialized;
using System.Text.RegularExpressions;

using System.Web.Configuration;

namespace Youz.Common.Helper
{
    /// <summary>
    /// This class provides helper methods for the <see cref="NHelper.Web"/> namespace.
    /// </summary>
    public class WebHelper
    {
        private static IDictionary<string, ImageFormat> _imageFormatsLookup;

        /// <summary>
        /// Static initializer.
        /// </summary>
        static WebHelper()
        {
            _imageFormatsLookup = new Dictionary<string, ImageFormat>();
            _imageFormatsLookup.Add("jpeg", ImageFormat.Jpeg);
            _imageFormatsLookup.Add("jpg", ImageFormat.Jpeg);
            _imageFormatsLookup.Add("gif", ImageFormat.Gif);
            _imageFormatsLookup.Add("png", ImageFormat.Png);
            _imageFormatsLookup.Add("image/jpeg", ImageFormat.Jpeg);
            _imageFormatsLookup.Add("image/jpg", ImageFormat.Jpeg);
            _imageFormatsLookup.Add("image/gif", ImageFormat.Gif);
            _imageFormatsLookup.Add("image/png", ImageFormat.Png);
        }

        #region WebFileHelper
        /// <summary>
        /// Get a remote web file.
        /// </summary>
        /// <param name="file">The remote URL</param>
        public static string GetFileContentsRemote(string file)
        {
            string content = string.Empty;
            try
            {
                Uri url = new Uri(file, UriKind.Absolute);
                using (WebClient client = new WebClient())
                {
                    // Load CSS content
                    client.Credentials = CredentialCache.DefaultNetworkCredentials;
                    content = client.DownloadString(url);
                }
                return content;
            }
            catch (System.Net.Sockets.SocketException)
            { return string.Empty; }
        }


        /// <summary>
        /// Retrieve local file contents.
        /// </summary>
        public static string GetFileContentsLocal(string file)
        {
            string path = HttpContext.Current.Server.MapPath(file);
            string content = string.Empty;
            try
            {
                using (StreamReader reader = new StreamReader(path))
                {
                    content = reader.ReadToEnd();
                }
            }
            catch
            { }
            return content;
        }


        /// <summary>
        /// Get the content of an upload file as a string.
        /// </summary>
        /// <param name="inputFile">Path to input file.</param>
        /// <returns>String with file contents.</returns>
        public static string GetContentOfFile(HtmlInputFile inputFile)
        {
            byte[] data = new byte[inputFile.PostedFile.ContentLength];
            int contentLength = inputFile.PostedFile.ContentLength;

            inputFile.PostedFile.InputStream.Read(data, 0, contentLength);
            MemoryStream stream = new MemoryStream(data);
            StreamReader reader = new StreamReader(stream);
            string importText = reader.ReadToEnd();
            return importText;
        }


        /// <summary>
        /// Get the content of an upload file as a string.
        /// </summary>
        /// <param name="inputFile">Path to input file.</param>
        /// <returns>Byte array with file contents.</returns>
        public static byte[] GetContentOfFileAsBytes(HtmlInputFile inputFile)
        {
            byte[] data = new byte[inputFile.PostedFile.ContentLength];
            int contentLength = inputFile.PostedFile.ContentLength;

            inputFile.PostedFile.InputStream.Read(data, 0, contentLength);
            return data;
        }


        /// <summary>
        /// Get the content of an upload file as a string.
        /// </summary>
        /// <param name="inputFile">Path to input file.</param>
        /// <returns>Byte array with file contents.</returns>
        public static byte[] GetContentOfFileAsBytes(HttpPostedFileBase inputFile)
        {
            byte[] data = new byte[inputFile.ContentLength];
            int contentLength = inputFile.ContentLength;

            inputFile.InputStream.Read(data, 0, contentLength);
            return data;
        }


        /// <summary>
        /// Gets the file extension of the file.
        /// </summary>
        /// <param name="inputFile">Path to file.</param>
        /// <returns>File extension.</returns>
        public static string GetFileExtension(HttpPostedFile inputFile)
        {
            if (inputFile == null || string.IsNullOrEmpty(inputFile.FileName))
                return string.Empty;

            string fileName = inputFile.FileName;

            int ndxExtensionPeriod = fileName.LastIndexOf(".");
            if (ndxExtensionPeriod < 0) { return string.Empty; }

            // Error could occurr with file name = test. (ok for now)
            // Check for .txt extension.
            string fileExtension = fileName.Substring(ndxExtensionPeriod + 1);
            fileExtension = fileExtension.Trim().ToLower();
            
            return fileExtension;
        }

        /// <summary>
        /// 檢查文件是否是圖片
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static bool HasImg(string filename)
        {
            if (string.IsNullOrEmpty(filename))
                return false;

            int ndxExtensionPeriod = filename.LastIndexOf(".");
            if (ndxExtensionPeriod < 0) { return false; }

            // Error could occurr with file name = test. (ok for now)
            // Check for .txt extension.
            string fileExtension = filename.Substring(ndxExtensionPeriod + 1);
            fileExtension = fileExtension.Trim().ToLower();

            if (!_imageFormatsLookup.ContainsKey(fileExtension))
                return false;

            return true;
        }

        /// <summary>
        /// Get the file extension as a image format.
        /// </summary>
        /// <param name="inputFile">Path to image file.</param>
        /// <returns>The format of the image file.</returns>
        public static ImageFormat GetFileExtensionAsFormat(HttpPostedFile inputFile)
        {
            string extension = GetFileExtension(inputFile);
            if (string.IsNullOrEmpty(extension)) return null;

            if (!_imageFormatsLookup.ContainsKey(extension)) return null;
            return _imageFormatsLookup[extension];
        }

        /// <summary>
        /// Checks if any media files were uploaded by checking the size of each posted file.
        /// </summary>
        /// <param name="request">Http request.</param>
        /// <returns>True if media files were uploaded.</returns>
        public static bool HasFiles(HttpRequestBase request)
        {
            if (request.Files == null || request.Files.Count == 0)
                return false;

            // Now check if files were uploaded.
            for (int ndx = 0; ndx < request.Files.Count; ndx++)
            {
                var file = request.Files[ndx];
                if (file.ContentLength > 0)
                    return true;
            }
            return false;
        }

        public static bool HasFiles()
        {
            return HasFiles(new HttpRequestWrapper(HttpContext.Current.Request));
        }

        public static bool HasFiles(string fileName)
        {
            var request = HttpContext.Current.Request;
            if (request.Files == null || request.Files.Count == 0)
                return false;

            var file = request.Files[fileName];
            if (file.ContentLength > 0)
                return true;

            return false;
        }

        /// <summary>
        /// 保存用户上传的文件
        /// </summary>
        /// <param name="path">保存路径</param>
        public static void SaveRequestFile(string path)
        {
            if (HttpContext.Current.Request.Files.Count > 0)
            {
                HttpContext.Current.Request.Files[0].SaveAs(path);
            }
        }

        #endregion

        #region request
        /// <summary>
        /// 获得指定Url参数的值
        /// </summary>
        /// <param name="strName">Url参数</param>
        /// <returns>Url参数的值</returns>
        public static string Get(string name)
        {
            if (HttpContext.Current.Request.QueryString[name] == null)
            {
                return "";
            }
            return HttpContext.Current.Request.QueryString[name].Trim();
        }

        /// <summary>
        /// 获得指定Url参数的值，为空则返回默认值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T Get<T>(string name)
        {
            return TypeHelper.ConvertTo<T>(Get(name));
        }

        /// <summary>
        /// 获得指定表单参数的值
        /// </summary>
        /// <param name="strName">表单参数</param>
        /// <returns>表单参数的值</returns>
        public static string Post(string name)
        {
            if (HttpContext.Current.Request.Form[name] == null)
            {
                return "";
            }
            return HttpContext.Current.Request.Form[name].Trim();
        }

        /// <summary>
        /// 获得指定Form参数的值，为空则返回默认值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T Post<T>(string name)
        {
            return TypeHelper.ConvertTo<T>(Post(name));
        }

        /// <summary>
        /// 判断当前页面是否接收到了Post请求
        /// </summary>
        /// <returns>是否接收到了Post请求</returns>
        public static bool IsPost()
        {
            return HttpContext.Current.Request.HttpMethod.Equals("POST");
        }

        /// <summary>
        /// 判断当前页面是否接收到了Get请求
        /// </summary>
        /// <returns>是否接收到了Get请求</returns>
        public static bool IsGet()
        {
            return HttpContext.Current.Request.HttpMethod.Equals("GET");
        }

        /// <summary>
        /// 判断当前访问是否来自浏览器软件
        /// </summary>
        /// <returns>当前访问是否来自浏览器软件</returns>
        public static bool IsBrowserRequest()
        {
            string[] BrowserName = { "ie", "opera", "netscape", "mozilla" };
            string curBrowser = HttpContext.Current.Request.Browser.Type.ToLower();
            for (int i = 0; i < BrowserName.Length; i++)
            {
                if (curBrowser.IndexOf(BrowserName[i]) >= 0)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 判断是否来自搜索引擎链接
        /// </summary>
        /// <returns>是否来自搜索引擎链接</returns>
        public static bool IsSearchEngineRequest()
        {
            string[] SearchEngine = { "google", "yahoo", "msn", "baidu", "sogou", "sohu", "sina", "163", "lycos", "tom" };
            string tmpReferrer = HttpContext.Current.Request.UrlReferrer.ToString().ToLower();
            for (int i = 0; i < SearchEngine.Length; i++)
            {
                if (tmpReferrer.IndexOf(SearchEngine[i]) >= 0)
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 通过时间获取一天内的开始时间
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string GetBeginDateTime(object obj)
        {
            DateTime dt;
            if (DateTime.TryParse(obj.ToString(), out dt))
            {
                return dt.ToString("yyyy-MM-dd");
            }
            return "";
        }
        /// <summary>
        /// 通过时间获取一天之内的结束时间
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string GetEndTime(object obj)
        {
            DateTime dt;
            if (DateTime.TryParse(obj.ToString(), out dt))
            {
                return dt.ToString("yyyy-MM-dd" + " 23:59:59 ");
            }
            return "";
        }
        /// <summary>
        /// 是否被判断为机器人 
        /// </summary>
        public static bool IsRobots
        {
            get
            {
                return IsSearchEngineRequest();
            }
        }

        /// <summary>
        /// Determines if the request being made is from the same host.
        /// Otherwise, most likely someone is leeching the image.
        /// </summary>
        /// <param name="requestDeniedImagePath">"~/images/backoff.gif"</param>
        /// <param name="ctx">Current http contenxt.</param>
        /// <param name="path">Physical path.</param>
        /// <returns>True of is being made from the same host.</returns>
        public static bool IsSelfRequest(HttpContext ctx, ref string path, string requestDeniedImagePath)
        {
            HttpRequest req = ctx.Request;
            path = req.PhysicalPath;

            if (req.UrlReferrer != null && req.UrlReferrer.Host.Length > 0)
            {
                if (CultureInfo.InvariantCulture.CompareInfo.Compare(req.Url.Host,
                    req.UrlReferrer.Host, CompareOptions.IgnoreCase) != 0)
                {
                    path = ctx.Server.MapPath(requestDeniedImagePath);
                    return false;
                }
            }
            return true;
        }

        public static bool IsSelfRequest()
        {
            HttpRequest req = HttpContext.Current.Request;

            if (req.UrlReferrer != null && req.UrlReferrer.Host.Length > 0)
            {
                if (CultureInfo.InvariantCulture.CompareInfo.Compare(req.Url.Host,
                    req.UrlReferrer.Host, CompareOptions.IgnoreCase) != 0)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 返回指定的服务器变量信息
        /// </summary>
        /// <param name="strName">服务器变量名</param>
        /// <returns>服务器变量信息</returns>
        public static string GetServerVariable(string strName)
        {
            //
            if (HttpContext.Current.Request.ServerVariables[strName] == null)
            {
                return "";
            }
            return HttpContext.Current.Request.ServerVariables[strName].ToString();
        }


        /// <summary>
        /// 获取上一个页面的地址
        /// </summary>
        /// <returns>上一个页面的地址</returns>
        public static string UrlReferrer
        {
            get
            {
                string retVal = null;

                try
                {
                    retVal = HttpContext.Current.Request.UrlReferrer.ToString();
                }
                catch { }

                if (retVal == null)
                    return "";

                return retVal;
            }
        }


        /// <summary>
        /// 得到当前完整主机头
        /// </summary>
        /// <returns></returns>
        public static string FullHost
        {
            get
            {
                HttpRequest request = System.Web.HttpContext.Current.Request;
                if (!request.Url.IsDefaultPort)
                {
                    return string.Format("{0}:{1}", request.Url.Host, request.Url.Port.ToString());
                }
                return request.Url.Host;
            }
        }

        /// <summary>
        /// 得到当前完整主机头(含http)
        /// </summary>
        /// <returns></returns>
        public static string FullHostHttp
        {
            get
            {
                HttpRequest request = System.Web.HttpContext.Current.Request;
                if (!request.Url.IsDefaultPort)
                {
                    return string.Format("http://{0}:{1}", request.Url.Host, request.Url.Port.ToString());
                }
                return "http://" + request.Url.Host;
            }
        }

        /// <summary>
        /// 得到主机头
        /// </summary>
        /// <returns></returns>
        public static string Host
        {
            get
            {
                return HttpContext.Current.Request.Url.Host;
            }
        }

        /// <summary>
        /// 获取当前请求的原始 URL(URL 中域信息之后的部分,包括查询字符串(如果存在))
        /// </summary>
        /// <returns>原始 URL</returns>
        public static string CurrentRawUrl
        {
            get
            {
                return HttpContext.Current.Request.RawUrl;
            }
        }

        /// <summary>
        /// 获得当前完整Url地址
        /// </summary>
        /// <returns>当前完整Url地址</returns>
        public static string CurrentUrl
        {
            get
            {
                return HttpContext.Current.Request.Url.ToString();
            }
        }

        /// <summary>
        /// 获得当前路径
        /// </summary>
        public static string CurrentPath
        {
            get
            {
                return HttpContext.Current.Request.Path;
            }
        }

        /// <summary>
        /// 获得当前页面的名称
        /// </summary>
        /// <returns>当前页面的名称</returns>
        public static string PageName
        {
            get
            {
                string[] urlArr = HttpContext.Current.Request.Url.AbsolutePath.Split('/');
                return urlArr[urlArr.Length - 1].ToLower();
            }
        }

        /// <summary>
        /// 网站主题，如果Theme为空则取StyleSheetTheme
        /// </summary>
        public static string SiteTheme
        {
            get
            {
                Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
                PagesSection pagesSection = config.GetSection("system.web/pages") as PagesSection;
                if (!string.IsNullOrEmpty(pagesSection.Theme))
                {
                    return pagesSection.Theme;
                }
                else if (!string.IsNullOrEmpty(pagesSection.StyleSheetTheme))
                {
                    return pagesSection.StyleSheetTheme;
                }
                else
                {
                    return "";
                }
            }
        }

        /// <summary>
        /// 获得当前页面客户端的IP
        /// </summary>
        /// <returns>当前页面客户端的IP</returns>
        public static string UserIP
        {
            get
            {
                string result = String.Empty;

                result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (null == result || result == String.Empty)
                {
                    result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
                }

                if (null == result || result == String.Empty)
                {
                    result = HttpContext.Current.Request.UserHostAddress;
                }

                if (null == result || result == String.Empty)
                {
                    return "0.0.0.0";
                }

                return result;
            }
        }

        /// <summary>
        /// 获得当前登录用户的用户名
        /// </summary>
        public static string UserName
        {
            get
            {
                return HttpContext.Current.User.Identity.Name;
            }
        }

        /// <summary>
        /// 获取访问者所使用的浏览器名
        /// </summary>
        public static string UserBrowser
        {
            get
            {
                string agent = HttpContext.Current.Request.UserAgent;
                if (agent == null || agent == string.Empty)
                    return "Unknown";
                agent = agent.ToLower();

                HttpBrowserCapabilities bc = HttpContext.Current.Request.Browser;
                if (agent.IndexOf("firefox") >= 0
                    || agent.IndexOf("firebird") >= 0
                    || agent.IndexOf("myie") >= 0
                    || agent.IndexOf("opera") >= 0
                    || agent.IndexOf("netscape") >= 0
                    || agent.IndexOf("msie") >= 0
                    )
                    return bc.Browser + bc.Version;

                return "Unknown";
            }
        }

        #endregion

        /// <summary>
        /// IP 地址字符串形式转换成长整型
        /// </summary>

        public static long IP2Numeric(string ip)
        {
            if (!ValidationHelper.IsIP(ip))
            {
                return -1;
            }

            string[] arr = ip.Split('.');
            long lng = long.Parse(arr[0]) * 16777216;
            lng += int.Parse(arr[1]) * 65536;
            lng += int.Parse(arr[2]) * 256;
            lng += int.Parse(arr[3]);
            return lng;
        }

        #region Regex Tag Parser
        /// <summary>
        /// Parses the text and obtains a collection of the tags to parse.
        /// </summary>
        /// <param name="text">List of parsed tags.</param>
        public IList<Tag> Parse(string tagname, string text)
        {
            string _text;
            string _tagName;
            List<Tag> _tags;

            _tagName = tagname;
            _text = text;
            _tags = new List<Tag>();
            // \<component\s{1}\s*(?<name>[\w]+)=\"(?<val>[\w]+)\"\s*/\>
            string pattern = "\\<" + _tagName + "\\s{1}\\s*(?<name>[\\w]+)=\\\"(?<val>[\\w]+)\\\"\\s*/\\>";
            var matches = Regex.Matches(_text, pattern, RegexOptions.IgnoreCase);

            if (matches != null && matches.Count > 0)
            {
                foreach (Match match in matches)
                {
                    Tag tag = new Tag();
                    tag.Attributes = new OrderedDictionary();
                    tag.Name = _tagName;
                    tag.Position = match.Index;
                    tag.Length = match.Length;
                    Group name = match.Groups["name"];
                    if (name != null)
                    {
                        Group val = match.Groups["val"];
                        if (val != null)
                        {
                            var keyValue = new Dictionary<string, string>();
                            keyValue.Add(name.Value, val.Value);

                            tag.Attributes[name.Value] = keyValue;
                            _tags.Add(tag);
                        }
                    }
                }
            }
            return _tags;
        }


        /// <summary>
        /// Class to represent an html/xml like tag with attributes.
        /// </summary>
        public class Tag
        {
            /// <summary>
            /// Tag name.
            /// </summary>
            public string Name;


            /// <summary>
            /// Tag attributes.
            /// </summary>
            public OrderedDictionary Attributes;


            /// <summary>
            /// Tag inner content.
            /// </summary>
            public string InnerContent;

            /// <summary>
            /// Length of the tag.
            /// </summary>
            public int Length;


            /// <summary>
            /// Starting index of the tag in the entire doc.
            /// </summary>
            public int Position;
        }

        #endregion

        public static void CreatePath(string path)
        {
            if (!System.IO.Directory.Exists(path))
            {
                System.IO.Directory.CreateDirectory(path);
            }
        }

        public static string HtmlEncode(string str)
        {
            return HttpContext.Current.Server.HtmlEncode(str);
        }

        public static string HtmlDecode(string str)
        {
            return HttpContext.Current.Server.HtmlDecode(str);
        }
    }
}